﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using JAMR.Rendering.Blocks;
using OpenTK;
using OpenTK.Graphics.OpenGL;

namespace JAMR.Rendering.GeometricObjects
{
    public class Cube
    {
        class Plane
        {
            public Vector3[] Points { get; set; }
            public Vector2[] TexturePoints { get; set; }
            public Side TextureSide { get; set; }
        }

        private static Plane[] cubePlanes = new Plane[]
        {
            // Top
            new Plane() { 
                    Points = new Vector3[] { new Vector3(0.5f, 0.5f, -0.5f), new Vector3(0.5f, 0.5f, 0.5f), new Vector3(-0.5f, 0.5f, 0.5f), new Vector3(-0.5f, 0.5f, -0.5f) },
                    TexturePoints = new Vector2[] { new Vector2(1, 0), new Vector2(0, 0), new Vector2(0, 1), new Vector2(1, 1) },
                    TextureSide = Side.Top
            },
            // Bottom
            new Plane() { 
                    Points = new Vector3[] { new Vector3(0.5f, -0.5f, -0.5f), new Vector3(0.5f, -0.5f, 0.5f), new Vector3(-0.5f, -0.5f, 0.5f), new Vector3(-0.5f, -0.5f, -0.5f),  },
                    TexturePoints = new Vector2[] { new Vector2(0, 1), new Vector2(1, 1), new Vector2(1, 0), new Vector2(0, 0) },
                    TextureSide = Side.Bottom
            },
            // Front
            new Plane() { 
                    Points = new Vector3[] { new Vector3(0.5f, -0.5f, -0.5f), new Vector3(0.5f, -0.5f, 0.5f), new Vector3(0.5f, 0.5f, 0.5f), new Vector3(0.5f, 0.5f, -0.5f),  },
                    TexturePoints = new Vector2[] { new Vector2(0, 1), new Vector2(1, 1), new Vector2(1, 0), new Vector2(0, 0) },
                    TextureSide = Side.Front
            },
            // Right
            new Plane() { 
                    Points = new Vector3[] { new Vector3(0.5f, -0.5f, 0.5f), new Vector3(-0.5f, -0.5f, 0.5f), new Vector3(-0.5f, 0.5f, 0.5f), new Vector3(0.5f, 0.5f, 0.5f),  },
                    TexturePoints = new Vector2[] { new Vector2(0, 1), new Vector2(1, 1), new Vector2(1, 0), new Vector2(0, 0) },
                    TextureSide = Side.Right
            },
            // Back
            new Plane() { 
                    Points = new Vector3[] { new Vector3(-0.5f, -0.5f, -0.5f), new Vector3(-0.5f, -0.5f, 0.5f), new Vector3(-0.5f, 0.5f, 0.5f), new Vector3(-0.5f, 0.5f, -0.5f),  },
                    TexturePoints = new Vector2[] { new Vector2(0, 1), new Vector2(1, 1), new Vector2(1, 0), new Vector2(0, 0) },
                    TextureSide = Side.Back
            },
            // Left
            new Plane() { 
                    Points = new Vector3[] { new Vector3(0.5f, -0.5f, -0.5f), new Vector3(0.5f, 0.5f, -0.5f), new Vector3(-0.5f, 0.5f, -0.5f), new Vector3(-0.5f, -0.5f, -0.5f) },
                    TexturePoints = new Vector2[] { new Vector2(1, 1), new Vector2(1, 0), new Vector2(0, 0), new Vector2(0, 1) },
                    TextureSide = Side.Left
            }
        };

        private enum Side { Top, Bottom, Front, Right, Back, Left }

        private Vector3 _middle;

        public Cube(Vector3 middle)
        {
            _middle = middle;
        }

        public void Draw(BlockTexture textures)
        {
            Draw(textures, Color.White);
        }
        public void Draw(BlockTexture textures, Color bgColor)
        {
            GL.Enable(EnableCap.Texture2D);
            GL.Color3(bgColor);

            TextureCache.Instance.SetCurrentTexture(textures.ITextureTop);

            foreach (var plane in cubePlanes)
            {
                switch (plane.TextureSide)
                {
                    case Side.Top:
                        TextureCache.Instance.SetCurrentTexture(textures.ITextureTop);
                        break;
                    case Side.Bottom:
                        TextureCache.Instance.SetCurrentTexture(textures.ITextureBottom);
                        break;
                    case Side.Front:
                        TextureCache.Instance.SetCurrentTexture(textures.ITextureFront);
                        break;
                    case Side.Right:
                        TextureCache.Instance.SetCurrentTexture(textures.ITextureRight);
                        break;
                    case Side.Back:
                        TextureCache.Instance.SetCurrentTexture(textures.ITextureBack);
                        break;
                    case Side.Left:
                        TextureCache.Instance.SetCurrentTexture(textures.ITextureLeft);
                        break;
                    default:
                        break;
                }

                // Draw all points
                GL.Begin(BeginMode.Quads);

                for (int i = 0; i < plane.Points.Length; i++)
                {
                    GL.TexCoord2(plane.TexturePoints[i]);
                    GL.Vertex3(_middle + plane.Points[i]);
                }

                GL.End();
            }

            GL.Disable(EnableCap.Texture2D);

            ErrorCode e = GL.GetError();
            if (e != ErrorCode.NoError)
            {
                Console.WriteLine("Error!");
            }
        }
    }
}
